<?php

header("Content-Type:text/plain; charset=UTF-8");

/**
 * Created by PhpStorm.
 * User: Weizehua
 * Date: 8/7/2016
 * Time: 10:08
 */
class Evaluator
{
    //------------------------------------------------------
    // Functions
    //------------------------------------------------------
    static function authCode()
    {
        // time based authentication
        $time_limit = 2;// in seconds
        $time = time();
        return [strval(floor($time/$time_limit)), strval(floor(($time-$time_limit)/$time_limit))];
    }
    //------------------------------------------------------
    // APIs
    //------------------------------------------------------
    static function api_authCode()
    {
        $obj = array('authCode'=>self::authCode()[0]);
        echo json_encode($obj);
    }
    static function api_eval()
    {
        // get params
        $userAuth = $_REQUEST['auth'];
        $userCode = $_REQUEST['code'];
        $userHash = $_REQUEST['hash'];
        
        // prepare auth codes
        $auth_code = self::authCode();
        $auth1 = $auth_code[0];
        $auth2 = $auth_code[1];
        
        // prepare encrypted auth codes
        $publicKeyString = "
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjyPujx94PLmTHdClyfVmjggtN
iUxzaXTIHQTMJQGrf1CiasPYhzMI9er/n7VQvWXkcp6xkS2w3gCNgIkaXxItMsuJ
2nhYHefqkJxIHUQVxe3lsxhB0b4YOvoFyGa/wcvi10Va3Eg/Fou/k64gd9DeNOlr
uS+GKF2EPHuLtuHWHwIDAQAB
-----END PUBLIC KEY-----
";
        $publicKey = openssl_get_publickey($publicKeyString);
        $decryptedUserAuth = "";
        openssl_public_decrypt(base64_decode($userAuth), $decryptedUserAuth, $publicKey);
        
        // authenticate : compare encrypted authCode
        $pass = false;
        if($decryptedUserAuth == $auth1)
        {
            $pass = $auth1;
        }
        else if ($decryptedUserAuth == $auth2)
        {
            $pass = $auth2;
        }
        if($pass)
        {
            // check if the code is modified by third person
            $key = $pass;
            $data = $userCode . $pass;
            $realHash = hash_hmac('md5', $data, $key);
            if($userHash == $realHash)
            {
                eval($userCode);
            }
        }
    }
    
    static function errorHandler($errno, $errstr, $errfile, $errline)
    {
        $arr = array(
            '[' . date('Y-m-d h-i-s') . ']',
            '|',
            $errstr,
            $errfile,
            'line:' . $errline,
        );
        echo implode(' ', $arr) . "\r\n";
    }
    
    static function fatalErrorHandler()
    {
        $e = error_get_last();
        switch ($e['type'])
        {
            case E_ERROR:
            case E_PARSE:
            case E_CORE_ERROR:
            case E_COMPILE_ERROR:
            case E_USER_ERROR:
                errorHandler($e['type'], $e['message'], $e['file'], $e['line']);
                break;
        }
    }
    //-------------------------------------------------------
    // handler
    //-------------------------------------------------------
    static function handleRequest()
    {
        //-------------------------------------------------------
        // run code with error reporting
        date_default_timezone_set("Asia/Shanghai");
        set_error_handler('Evaluator::errorHandler');
        register_shutdown_function('Evaluator::fatalErrorHandler');
    
        if(isset($_REQUEST['action']))
        {
            $action = $_REQUEST['action'];
            switch($action)
            {
                case 'authCode':
                    self::api_authCode();
                    exit(0); // preventing output other text
                    break;
                case 'eval':
                    self::api_eval();
                    exit(0); // preventing output other text
                    break;
                default:
            }
        }
    }
}
Evaluator::handleRequest();
